home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / QuickTime VR / MacOS / QuickDraw™ 3D 1.0.6F4 SDK / Samples / SampleCode / Unsupported Libraries / PICTio.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-05  |  18.8 KB  |  640 lines  |  [TEXT/MPS ]

  1. /******************************************************************************
  2.  **                                                                             **
  3.  **     Module:        PICTio.c                                                 **
  4.  **                                                                          **
  5.  **                                                                          **
  6.  **                                                                          **
  7.  **     Purpose:     Read and write PICT files.
  8.  **
  9.  **                    There are two different "read" routines.
  10.  **                    One uses QuickDraw, and so can draw any kind of PICT,
  11.  **                    but this only works on Macintoshes.
  12.  **
  13.  **                    The other parses the PICT file directly, and only reads
  14.  **                    in a subset of the PICT opcodes, most particularly
  15.  **                    24-32 bit images (DirectBitsRect). This works cross
  16.  **                    platform, at least on big-endian machines (it works on
  17.  **                    the SGI).
  18.  **
  19.  **                    The "write" routine comes in only one version.
  20.  **                    Both Macintoshes and non-Macintoshes write out PICT
  21.  **                    files directly. One advantage to the interface is that
  22.  **                    images may be written out in a piecewise fashion,
  23.  **                    one scaline at a time. This is difficult if not
  24.  **                    impossible to do using the Macintosh toolbox. The
  25.  **                    incremental writing of an image is handy in particular
  26.  **                    when band-rendering or otherwise rendering on a machine
  27.  **                    with a small amount of memory compared with the
  28.  **                    rendering task.
  29.  **                                                                          **
  30.  **                                                                          **
  31.  **                                                                          **
  32.  **     Copyright (C) 1992-1995 Apple Computer, Inc.  All rights reserved.     **
  33.  **                                                                          **
  34.  **                                                                          **
  35.  *****************************************************************************/
  36.  
  37. #if defined(applec) || defined(THINK_C) || defined(__MWERKS__)
  38. # include <Quickdraw.h>
  39. # include <Memory.h>
  40. #endif /* defined(applec) || defined(THINK_C) || defined(__MWERKS__) */
  41.  
  42. #include <stdio.h>
  43. #include <stdlib.h>
  44. #include "QD3D.h"
  45. #include "PackBytes.h"
  46. #include "PICTio.h"
  47.  
  48.  
  49.  
  50. #if defined(applec) || defined(THINK_C) || defined(__MWERKS__)
  51.  
  52. /****************************************************************
  53.  * Read PICT - Macintosh version.
  54.  ****************************************************************/
  55.  
  56. static FILE *PICTfd;
  57.  
  58.  
  59. /*===========================================================================*\
  60.  *
  61.  *    Routine:    GetPICTData()
  62.  *
  63.  *    Comments:    Bottleneck proc.
  64.  *
  65. \*===========================================================================*/
  66.  
  67. /* This is the replacement for the StdGetPic routine */
  68. static pascal void GetPICTData(
  69.     Ptr     dataPtr, 
  70.     short     byteCount)
  71. {
  72.     fread(dataPtr, 1, byteCount, PICTfd);
  73. }
  74.  
  75. /*===========================================================================*\
  76.  *
  77.  *    Routine:    ErReadPICT()
  78.  *
  79.  *    Comments:    PICT reading
  80.  *
  81. \*===========================================================================*/
  82.  
  83. unsigned char *ErReadPICT(        /* Returns a pointer to the baseAddr */
  84.     long             *width,     /* Returns the width of the image */
  85.     long             *height,     /* Returns the height of the image */
  86.     long             *rowBytes,     /* Returns the rowBytes of the image */
  87.     FILE             *fd            /* The I/O descriptor */
  88. )
  89. {
  90.     unsigned char *image;
  91.  
  92.     CQDProcs     myProcs;
  93.     PicHandle     myPicture;
  94.     Rect         pictR;
  95.     CGrafPort     myPort;
  96.     GrafPtr     savePort;
  97.     PixMap         *pm;
  98.     GDHandle     gd, saveGD;
  99.     
  100.     PICTfd = fd;
  101.  
  102.  
  103.     /* Read the picture frame size */
  104.     fseek(fd, 512L, 0);
  105.     myPicture = (PicHandle)NewHandle(sizeof (Picture));
  106.     HLock((Handle)myPicture);
  107.     fread(*myPicture, sizeof(Picture), 1, fd);
  108.     pictR = (*myPicture)->picFrame;
  109.     HUnlock((Handle)myPicture);
  110.  
  111.     /* Allocate a bitmap */
  112.     *width = pictR.right - pictR.left;
  113.     *height = pictR.bottom - pictR.top;
  114.     *rowBytes = (*width) * 4;
  115.     if ((image = malloc((*rowBytes) * (*height))) == NULL) {
  116.         fprintf(stderr, "Can't alloc image\n");
  117.         return (NULL);
  118.     }
  119.  
  120.     GetPort(&savePort);
  121.     
  122.     /* Allocate a GDevice */
  123.     gd = NewGDevice(3, -1);
  124.     (*gd)->gdType = 2;
  125.     pm = *((*gd)->gdPMap);
  126.     pm->rowBytes = 0x8000 | *rowBytes;
  127.     pm->baseAddr = (Ptr)image;
  128.     pm->bounds = pictR;
  129.     pm->pixelType = 16;
  130.     pm->pixelSize = 32;
  131.     pm->cmpCount = 3;
  132.     pm->cmpSize = 8;
  133.     pm->pmTable = 0;
  134.     (*gd)->gdRect = pictR;
  135.     SetDeviceAttribute(gd, 0, 1);
  136.     SetDeviceAttribute(gd, 11, 0);
  137.     SetDeviceAttribute(gd, 13, 0);
  138.     SetDeviceAttribute(gd, 14, 0);
  139.     SetDeviceAttribute(gd, 15, 1);
  140.     
  141.     saveGD = GetGDevice();
  142.     SetGDevice(gd);
  143.  
  144.     /* Allocate and initialize a CGrafPort */
  145.     OpenCPort(&myPort);
  146.     CopyPixMap((*gd)->gdPMap, myPort.portPixMap);
  147.     
  148.     /* Hack the visRgn */
  149.     RectRgn(myPort.visRgn, &pictR);
  150.  
  151.     /* change the procs in the port */
  152.     SetStdCProcs(&myProcs);
  153. #if defined(__MWERKS__) || defined(ppcinterfaces) || (THINK_C > 6)
  154.     myProcs.getPicProc = NewQDGetPicProc(GetPICTData);
  155. #elif defined(THINK_C) && (THINK_C <= 6)
  156.     myProcs.getPicProc = (Ptr)GetPICTData;
  157. #else
  158.     myProcs.getPicProc = GetPICTData;
  159. #endif
  160.     myPort.grafProcs = &myProcs;
  161.     
  162.     SetPort((GrafPtr)&myPort);
  163.  
  164.     DrawPicture(myPicture, &pictR);
  165.  
  166.     SetPort(savePort);
  167.     SetGDevice(saveGD);
  168.     CloseCPort(&myPort);
  169.     DisposGDevice(gd);
  170.  
  171.     KillPicture(myPicture);
  172.     
  173.     return (image);
  174. }
  175.  
  176. #else /* !macintosh */
  177.  
  178.  
  179. /****************************************************************
  180.  * Read PICT - Non-Macintosh method: reading only 24-bit images.
  181.  ****************************************************************/
  182.  
  183. typedef char     *Ptr;
  184. typedef long     Fixed;
  185. typedef void    **CTabHandle;
  186.  
  187. typedef struct Rect {
  188.     short top;
  189.     short left;
  190.     short bottom;
  191.     short right;
  192. } Rect;
  193.  
  194. typedef struct Picture {
  195.     short picSize;
  196.     Rect picFrame;
  197. } Picture;
  198.  
  199. typedef struct PixMap {
  200.     Ptr baseAddr;                   /*pointer to image*/
  201.     short rowBytes;                 /*offset to next line*/
  202.     Rect bounds;                    /*encloses bitmap*/
  203.     short pmVersion;                /*pixMap version number*/
  204.     short packType;                 /*defines packing format*/
  205.     long packSize;                  /*length of pixel data*/
  206.     Fixed hRes;                     /*horiz. resolution (ppi)*/
  207.     Fixed vRes;                     /*vert. resolution (ppi)*/
  208.     short pixelType;                /*defines pixel type*/
  209.     short pixelSize;                /*# bits in pixel*/
  210.     short cmpCount;                 /*# components in pixel*/
  211.     short cmpSize;                  /*# bits per component*/
  212.     long planeBytes;                /*offset to next plane*/
  213.     CTabHandle pmTable;             /*color map for this pixMap*/
  214.     long pmReserved;                /*for future use. MUST BE 0*/
  215. } PixMap;
  216.  
  217.  
  218. /*===========================================================================*\
  219.  *
  220.  *    Routine:    ErReadPICT()
  221.  *
  222.  *    Comments:    This reads only 24-bit images, but works on any machine.
  223.  *
  224. \*===========================================================================*/
  225.  
  226. unsigned char *ErReadPICT(        /* Returns a pointer to the baseAddr */
  227.     long             *width,     /* Returns the width of the image */
  228.     long             *height,     /* Returns the height of the image */
  229.     long             *rowBytes,     /* Returns the rowBytes of the image */
  230.     FILE             *f            /* The I/O descriptor */
  231. )
  232. {
  233.     unsigned char *image = NULL;
  234.     Picture pictHeader;    /* Assume that we like what it says */
  235.     struct     VersionBundle { short versionOpcode, version; } versionBundle;
  236.     typedef struct { unsigned char a, r, g, b; } TColorI;
  237.  
  238.     fseek(f, 512L, 0);    /* Skip 512 byte header */
  239.  
  240.     fread(&pictHeader, sizeof(pictHeader), 1, f);
  241.     
  242.     fread(&versionBundle, sizeof(versionBundle), 1, f);
  243.     if (versionBundle.versionOpcode != 0x0011 || versionBundle.version != 0x02FF) {
  244.         fprintf(stderr, 
  245.                 "Bad version bundle: %04X %04X", 
  246.                 versionBundle.versionOpcode, 
  247.                 versionBundle.version);
  248.         return (0);
  249.     }
  250.     
  251.     for (;;) {
  252.         short opCode;
  253.         if (fread(&opCode, sizeof(opCode), 1, f) == 0)
  254.             break;
  255.         switch (opCode) {
  256.             case 0x0000:    /* NOP */
  257.                 break;
  258.             
  259.             case 0x0011:    /* Version */
  260.             {
  261.                 short version;
  262.                 fread(&version, sizeof(version), 1, f);
  263.                 if (version != 0x02FF) {
  264.                     fprintf(stderr, "Version %04X != 0x02FF", version);
  265.                     return (0);
  266.                 }
  267.             } break;
  268.             
  269.             case 0x0C00:    /* Header */
  270.             {
  271.                 struct HeaderBundle {
  272.                     long    sizeField;        /* -1 */
  273.                     Fixed    left;
  274.                     Fixed    top;
  275.                     Fixed    right;
  276.                     Fixed    bottom;
  277.                     long    appleReserved;    /* 0 */
  278.                 } headerBundle;
  279.                 fread(&headerBundle, sizeof(headerBundle), 1, f);
  280.             } break;
  281.  
  282.             case 0x001E:    /* defHilite */
  283.                 break;
  284.             
  285.             case 0x0001:    /* ClipRegion */
  286.             {
  287.                 unsigned short clipRgnSize;
  288.                 fread(&clipRgnSize, sizeof(clipRgnSize), 1, f);
  289.                 fseek(f, (long)(clipRgnSize-2), 1);        /* Skip clip region */
  290.             } break;
  291.             
  292.             case 0x009A:    /* directBitsRect */
  293.             {    
  294.                 struct ImageStuff {
  295.                     PixMap    pixmap;
  296.                     Rect    srcRect;
  297.                     Rect    dstRect;
  298.                     short    mode;
  299.                 } imageStuff;
  300.                 
  301.                 /* Get a buffer to hold the image */
  302. #if defined(applec) || defined(THINK_C)
  303.                 fread(&imageStuff, sizeof(imageStuff), 1, f);
  304. #else /* !macintosh */
  305.                 /* get around non-longword alignment */
  306.                 fread(&imageStuff.pixmap.baseAddr,        sizeof(long),    1,    f);
  307.                 fread(&imageStuff.pixmap.rowBytes,        sizeof(short),    1,    f);
  308.                 fread(&imageStuff.pixmap.bounds,        sizeof(short),    4,    f);    /* left, top, right, bottom */
  309.                 fread(&imageStuff.pixmap.pmVersion,        sizeof(short),    2,    f);    /* pmVersion, packType */
  310.                 fread(&imageStuff.pixmap.packSize,        sizeof(long),    1,    f);
  311.                 fread(&imageStuff.pixmap.hRes,            sizeof(Fixed),    2,    f);    /* hRes, vRes */
  312.                 fread(&imageStuff.pixmap.pixelType,        sizeof(short),    4,    f);    /* pixelType, pixelSize, cmpCount, cmpSize */
  313.                 fread(&imageStuff.pixmap.planeBytes,    sizeof(long),    3,    f);    /* planeBytes, pmTable, pmReserved */
  314.                 fread(&imageStuff.srcRect,                sizeof(short),    4,    f);    /* left, top, right, bottom */
  315.                 fread(&imageStuff.dstRect,                sizeof(short),    4,    f);    /* left, top, right, bottom */
  316.                 fread(&imageStuff.mode,                    sizeof(short),    1,    f);
  317. #endif /* macintosh */
  318.  
  319.                 *width = imageStuff.srcRect.right - imageStuff.srcRect.left;
  320.                 *height = imageStuff.srcRect.bottom - imageStuff.srcRect.top;
  321.                 *rowBytes = 4 * (*width);
  322.                 image = malloc(*rowBytes * (*height));
  323.                     
  324.                 if (image != NULL) {
  325.                     char lineBuffer[5000];    /* scanline of components */
  326.                     char compLine[5000];    /* compressed scanline of components */
  327.                     register long i;
  328.                     int j;
  329.                     register char *p, *q;
  330.                     char *q0;
  331.                     int wordByteCount = (int)((imageStuff.pixmap.rowBytes & 0x3FFF) > 250);    /* If byteCount is a word */
  332.  
  333.                     for (q0 = (char *)image, j = *height; j--; q0 += *rowBytes) {
  334.                     
  335.                         /* Read a compressed scanline */
  336.                         if (wordByteCount) {
  337.                             unsigned short size;
  338.                             fread(&size, sizeof(size), 1, f);
  339.                             fread(compLine, size, 1, f);
  340.                         }
  341.                         else {
  342.                             unsigned char size;
  343.                             fread(&size, sizeof(size), 1, f);
  344.                             fread(compLine, size, 1, f);
  345.                         }
  346.                         
  347.                         /* Decompress the scanline */
  348.                         UnpackBytes(compLine, lineBuffer, 3*(*width));
  349.                     
  350.                         /* Interlace components into image */
  351.                         p = lineBuffer;
  352.                         for (i = *width, q = (char *)(&((TColorI*)q0)->r); i--; p++, q += sizeof(TColorI))
  353.                             *q = *p;    /* Comb out red */
  354.                         for (i = *width, q = (char *)(&((TColorI*)q0)->g); i--; p++, q += sizeof(TColorI))
  355.                             *q = *p;    /* Comb out green */
  356.                         for (i = *width, q = (char *)(&((TColorI*)q0)->b); i--; p++, q += sizeof(TColorI))
  357.                             *q = *p;    /* Comb out blue */
  358.                     }
  359.                     if (ftell(f) & 1)
  360.                         getc(f);
  361.                 }
  362.                 else {
  363.                     fprintf(stderr, "Unable to allocate buffer(%d, %d) for ReadPICT", *width, *height);
  364.                 }
  365.             } break;
  366.             
  367.             case 0x00FF:    /* End opcode */
  368.                 return (image);
  369.                 
  370.             default:
  371.                 fprintf(stderr, "Unknown opcode: %04X", opCode);
  372.                 return (image);
  373.         }
  374.     }
  375.     
  376.     return (NULL);
  377. }
  378.  
  379. #endif /* !macintosh */
  380.  
  381.  
  382.  
  383. typedef struct PICTheader {
  384.     /* 512 bytes of 0's */
  385.     Picture    picture;
  386.  
  387.     short    versionOpcode;    /* 0x0011 */
  388.     short    version;        /* 0x02FF */
  389.     
  390.     short    headerOpcode;    /* 0x0C00 */
  391.     long    sizeField;        /* -1 */
  392.     Fixed    left;
  393.     Fixed    top;
  394.     Fixed    right;
  395.     Fixed    bottom;
  396.     long    appleReserved;    /* 0 */
  397.     
  398.     short    maxClipRegion[6];    /* 0001 000A 8001 8001 7FFF 7FFF */
  399.     
  400.     short    directBitsRect;    /* 009A */
  401.     PixMap    pixmap;
  402.     Rect    srcRect;
  403.     Rect    dstRect;
  404.     short    mode;
  405.     /* PixelData */
  406. } PICTHeader;
  407.  
  408.  
  409. /*===========================================================================*\
  410.  *
  411.  *    Routine:    StartWritePICT()
  412.  *
  413.  *    Comments:    Write header for a 24-bit PICT file without using QuickDraw.
  414.  *
  415. \*===========================================================================*/
  416.  
  417. long StartWritePICT(
  418.     long     width, 
  419.     long     height, 
  420.     FILE     *f
  421. )
  422. {
  423.     struct PICTheader myPICTheader;
  424.  
  425.     {    /* Write out the 512 byte header pad */
  426.         long headPad[512/sizeof(long)];
  427.         register long *lp = headPad;
  428.         register int i;
  429.         char *cHeadPad = (char *)headPad;
  430.         
  431.         for (i = 512/sizeof(long); i--; *lp++ = 0) {
  432.             /* do nothing */ ;    /* Clear header pad */
  433.         }
  434.         
  435.         cHeadPad[0] = 'P';    /* Record the type of the file */
  436.         cHeadPad[1] = 'I';
  437.         cHeadPad[2] = 'C';
  438.         cHeadPad[3] = 'T';
  439.         
  440.         fwrite(cHeadPad, 1, 512, f);    /* Write out the header pad */
  441.     }
  442.     
  443.     /* Make SURE the size of the image is adequately recorded */
  444.     myPICTheader.picture.picSize =            0;
  445.     myPICTheader.picture.picFrame.top =        0;
  446.     myPICTheader.picture.picFrame.left =    0;
  447.     myPICTheader.picture.picFrame.bottom =    height;
  448.     myPICTheader.picture.picFrame.right =    width;
  449.     myPICTheader.versionOpcode =            0x0011;
  450.     myPICTheader.version =                    0x02FF;    /* Version 2 */
  451.     myPICTheader.headerOpcode =                0x0C00;
  452.     myPICTheader.sizeField =                -1;
  453.     myPICTheader.left =                        0;
  454.     myPICTheader.top =                        0;
  455.     myPICTheader.right =                    width << 16;
  456.     myPICTheader.bottom =                    height << 16;
  457.     myPICTheader.appleReserved =            0;
  458.     myPICTheader.maxClipRegion[0] =            0x0001;    /* Clip region opcode */
  459.     myPICTheader.maxClipRegion[1] =            0x000A;    /* sizeof (Rect) + 2 */
  460.     myPICTheader.maxClipRegion[2] =            0x8001;    /* top */
  461.     myPICTheader.maxClipRegion[3] =            0x8001;    /* left */
  462.     myPICTheader.maxClipRegion[4] =            0x7FFF;    /* bottom */
  463.     myPICTheader.maxClipRegion[5] =            0x7FFF;    /* right */
  464.     myPICTheader.directBitsRect =            0x009A;
  465.     myPICTheader.pixmap.baseAddr =            (Ptr)0x000000FF;
  466.     myPICTheader.pixmap.rowBytes =            (4 * width) | 0x8000;
  467.     myPICTheader.pixmap.bounds.top =        0;
  468.     myPICTheader.pixmap.bounds.left =        0;
  469.     myPICTheader.pixmap.bounds.bottom =        height;
  470.     myPICTheader.pixmap.bounds.right =        width;
  471.     myPICTheader.pixmap.pmVersion =            0;
  472.     myPICTheader.pixmap.packType =            4;
  473.     myPICTheader.pixmap.packSize =            0;
  474.     myPICTheader.pixmap.hRes =                72 << 16;
  475.     myPICTheader.pixmap.vRes =                72 << 16;
  476.     myPICTheader.pixmap.pixelType =            16;
  477.     myPICTheader.pixmap.pixelSize =            32;
  478.     myPICTheader.pixmap.cmpCount =            3;
  479.     myPICTheader.pixmap.cmpSize =            8;
  480.     myPICTheader.pixmap.planeBytes =        0;
  481.     myPICTheader.pixmap.pmTable =            0;
  482.     myPICTheader.pixmap.pmReserved =        0;
  483.     myPICTheader.srcRect.top =                0;
  484.     myPICTheader.srcRect.left =                0;
  485.     myPICTheader.srcRect.bottom =            height;
  486.     myPICTheader.srcRect.right =            width;
  487.     myPICTheader.dstRect.top =                0;
  488.     myPICTheader.dstRect.left =                0;
  489.     myPICTheader.dstRect.bottom =            height;
  490.     myPICTheader.dstRect.right =            width;
  491.     myPICTheader.mode =                        0x0040;    /* Dither */
  492.     
  493. #if defined(applec) || defined(THINK_C)
  494.     fwrite(&myPICTheader, sizeof(myPICTheader), 1, f);
  495. #else /* !macintosh, but not for the Cray */
  496.     fwrite(&myPICTheader.picture.picSize,    sizeof(short),    1,    f);
  497.     fwrite(&myPICTheader.picture.picFrame,    sizeof(short),    4,    f);    /* left, top, right, bottom */
  498.  
  499.     fwrite(&myPICTheader.versionOpcode,        sizeof(short),    2,    f);    /* versionOpCode, version */
  500.  
  501.     fwrite(&myPICTheader.headerOpcode,        sizeof(short),    1,    f);
  502.     fwrite(&myPICTheader.sizeField,            sizeof(long),    1,    f);
  503.     fwrite(&myPICTheader.left,                sizeof(Fixed),    4,    f);    /* left, top, right, bottom */
  504.     fwrite(&myPICTheader.appleReserved,        sizeof(long),    1,    f);
  505.  
  506.     fwrite(myPICTheader.maxClipRegion,        sizeof(short),    6,    f);
  507.  
  508.     fwrite(&myPICTheader.directBitsRect,    sizeof(short),    1,    f);
  509.     fwrite(&myPICTheader.pixmap.baseAddr,    sizeof(long),    1,    f);
  510.     fwrite(&myPICTheader.pixmap.rowBytes,    sizeof(short),    1,    f);
  511.     fwrite(&myPICTheader.pixmap.bounds,        sizeof(short),    4,    f);    /* left, top, right, bottom */
  512.     fwrite(&myPICTheader.pixmap.pmVersion,    sizeof(short),    2,    f);    /* pmVersion, packType */
  513.     fwrite(&myPICTheader.pixmap.packSize,    sizeof(long),    1,    f);
  514.     fwrite(&myPICTheader.pixmap.hRes,        sizeof(Fixed),    2,    f);    /* hRes, vRes */
  515.     fwrite(&myPICTheader.pixmap.pixelType,    sizeof(short),    4,    f);    /* pixelType, pixelSize, cmpCount, cmpSize */
  516.     fwrite(&myPICTheader.pixmap.planeBytes,    sizeof(long),    3,    f);    /* planeBytes, pmTable, pmReserved */
  517.     fwrite(&myPICTheader.srcRect,            sizeof(short),    4,    f);    /* left, top, right, bottom */
  518.     fwrite(&myPICTheader.dstRect,            sizeof(short),    4,    f);    /* left, top, right, bottom */
  519.     fwrite(&myPICTheader.mode,                sizeof(short),    1,    f);
  520. #endif /* macintosh */
  521.  
  522.     return (!ferror(f));    /* 1 if no error, 0 otherwise */
  523. }
  524.  
  525.  
  526.  
  527. /*===========================================================================*\
  528.  *
  529.  *    Routine:    WritePICTLines()
  530.  *
  531.  *    Comments:    Write the specified number of lines.
  532.  *
  533. \*===========================================================================*/
  534.  
  535. long WritePICTLines(
  536.     unsigned char     *buf, 
  537.     long             width, 
  538.     long             height, 
  539.     long             rowBytes, 
  540.     FILE             *f
  541. )
  542. {
  543.     unsigned char             lineBuffer[5200];        /* scanline of components */
  544.     unsigned char             compLine[5200];    /* compressed scanline of components */
  545.     register int             i;
  546.     int                     wordByteCount;
  547.     register unsigned char     *p, *q;
  548.     unsigned char             *q0;
  549.  
  550.     wordByteCount = (int)(width > 250/4);    /* If byteCount is a word */
  551.     
  552.     for (q0 = buf; height--; q0 += rowBytes) {
  553.     
  554.         /* Comb components out of image */
  555.         p = lineBuffer;
  556.         for (i = width, q = q0 + 1; i--; p++, q += 4)
  557.             *p = *q;    /* Comb out red */
  558.         for (i = width, q = q0 + 2; i--; p++, q += 4)
  559.             *p = *q;    /* Comb out green */
  560.         for (i = width, q = q0 + 3; i--; p++, q += 4)
  561.             *p = *q;    /* Comb out blue */
  562.     
  563.         /* Write out the size of this compressed scanline */
  564.         i = (int)PackBytes((char *)lineBuffer, (char *)compLine, 3*width);
  565.         if (wordByteCount) {
  566.             unsigned char size[2];
  567.             size[0] = (unsigned char)(i >> 8);
  568.             size[1] = (unsigned char)i;
  569.             fwrite(size, 2, 1, f);
  570.         }
  571.         else {
  572.             unsigned char size = i;
  573.             fwrite(&size, 1, 1, f);
  574.         }
  575.         
  576.         /* Write out the compressed scanline */
  577.         fwrite(compLine, 1, i, f);
  578.     }
  579.     
  580.     return (!ferror(f));    /* 1 if no error, 0 otherwise */
  581. }
  582.  
  583.  
  584. /*===========================================================================*\
  585.  *
  586.  *    Routine:    EndWritePICT()
  587.  *
  588.  *    Comments:    Close up PICT file.
  589.  *
  590. \*===========================================================================*/
  591.  
  592. long EndWritePICT(
  593.     FILE     *f
  594. )
  595. {
  596.     short code;
  597.     
  598.     /* Write end opcode */
  599.     if (ftell(f) & 1) putc(0, f);    /* Make sure we are word aligned */
  600.     code = 0x00FF;
  601.     fwrite(&code, sizeof(short), 1, f);
  602.     
  603.     /* Backfit picSize */
  604.     code = (short)(ftell(f) - 512L);
  605.     fseek(f, 512L, 0);
  606.     fwrite(&code, 2, 1, f);
  607.     
  608.     return (!ferror(f));    /* 1 if no error, 0 otherwise */
  609. }
  610.  
  611.  
  612. /*===========================================================================*\
  613.  *
  614.  *    Routine:    ErWritePICT()
  615.  *
  616.  *    Comments:    Write a PICT file.
  617.  *
  618. \*===========================================================================*/
  619.  
  620. long ErWritePICT(
  621.     unsigned char     *baseAddr, 
  622.     long             width, 
  623.     long             height, 
  624.     long             rowBytes, 
  625.     FILE             *f
  626. )
  627. {    
  628.     if (height < 0) {
  629.         height = -height;    
  630.         /* This takes care of the case when Y goes up; rowBytes should be < 0 */
  631.     }
  632.     
  633.     StartWritePICT(width, height, f);
  634.     WritePICTLines(baseAddr, width, height, rowBytes, f);
  635.     EndWritePICT(f);
  636.     
  637.     return (!ferror(f));    /* 1 if no error, 0 otherwise */
  638. }
  639.  
  640.